
package TCPTools;

import Model.PathFile;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;


/**
 * La classe ClientTCP cree un client chargé du transfert de fichier 
 *
 * @author      Frank Djomo
 * @author      Christelle SIAGO HAPPI
 * @author      djomopoueme@gmail.com
 * @author      christelle.siagohappi@gmail.com
 * @version     1.0
 */
public class ClientTCP extends Thread implements Runnable{
      
 
    private Socket          socket ;
    private BufferedReader  entree ;  //entree flux fichier à lire
    private BufferedWriter  sortie ; //Sortie du flux de la socket
    private boolean         isStart ;
    private PathFile       fileToSend ;
    private int           portServeur ;  
    private  InetAddress          addressServer;

    private ProgressBar   barreDeProgression ;
    
      
    /**
    *  Cree un client TCP pour le transfert de fichier
    *  @param addressServer     Adresse IP du serveur en attente de connexion
    *  @param portServeur       Port d'ecoute du serveur
    *  @param file              PathFile representant le fichier à transfert
    *  @see PathFile
    */
    public ClientTCP(InetAddress addressServer ,int portServeur,PathFile file)
    {
         this.setAddressServeur(addressServer);
         this.setPortServeur(portServeur);
         this.setFile(file);
         barreDeProgression = new ProgressBar(file.getFile().length(), 'e');
         isStart=false;
    }
    /**
    *  Cree un client TCP pour le transfert de fichier
    *  @param addressServer     Nom du serveur en attente de connexion
    *  @param portServeur       Port d'ecoute du serveur
    *  @param file              PathFile representant le fichier à transfert
    *  @see PathFile
    */
    public ClientTCP(String addressServer ,int portServeur,PathFile file) throws UnknownHostException
    {
         this(InetAddress.getByName(addressServer),portServeur,file);  
    }

    private void setPortServeur(int port){
       if(port>1024) portServeur= port;
    }
    
    private  void setAddressServeur(InetAddress address){
        this.addressServer =address;
    }
    
    private  void setFile(PathFile file){
        this.fileToSend=new PathFile(file);
    }   
    /**
    *  Lance le client TCP pour un transfert de fichier
    *  Cette methode realise 4 opérations :
    * <ul>
    * <li> Connexion au serveur
    * <li> Ouverture des flux d'entrée et de sortie
    * <li> Envoi des données 
    * <li> Fermeture des flux
    * </ul>
    */
    private void lancerClient(){
        
        //Etape 2 : attente d'une connexion
        try {
            ClientTCP.sleep(1000); // Pause de 1 secondes
            seConnecter();
            } 
        catch (InterruptedException ex) {
            Logger.getLogger(ClientTCP.class.getName()).log(Level.SEVERE, null, ex);
        }
        catch (IOException ex) {
            Logger.getLogger(ClientTCP.class.getName()).log(Level.SEVERE, null, ex);
        }

        //etape 3 : Recuperation des flux de la connexion
        System.out.println("Connexion au serveur reussie port  Client >: "+socket);        
        try {          
            openFlux();
        } catch (IOException ex) {
            Logger.getLogger(ClientTCP.class.getName()).log(Level.SEVERE, null, ex);
        }

        //etape 4 : Traiter la connexion .
        try {          
             envoiData();
        } catch (IOException ex) {
            Logger.getLogger(ClientTCP.class.getName()).log(Level.SEVERE, null, ex);
        }

        //Etape 5: Fermer les flux 
        closeFlux();     
    }
    
    
    /**
    * Connexion au serveur
    * @throws  IOException
    * 
    */
    private void seConnecter() throws IOException
    {
        try{
            System.out.println("Tentative de connection .... :\n");
            socket = new Socket(addressServer,portServeur);

        }catch (java.io.IOException ex){
            Logger.getLogger(ClientTCP.class.getName()).log(Level.SEVERE, null, ex);
            socket.close();
        }
    }
    /**
    * Ouverture des flux d'entrée et sortie
    * @throws IOException
    */
    private void openFlux() throws IOException
    {
        try{
             //Recuperation des flux
            sortie       = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        }catch (java.io.IOException ex){
            Logger.getLogger(ServeurTCP.class.getName()).log(Level.SEVERE, null, ex);         
                sortie.close();   
        }
    }

    /**
    * Envoie des données
    */
    private void envoiData() throws  IOException{
        
        Vitesse vitesseTransfert = new Vitesse();
        
        boolean transfert = true;
	//byte[] buffer ;
       
	int octectLu = 0;
        int octectTraite = 0;
        
        int size = (int)fileToSend.getFile().length();
        char[] ligneLu = new char[size];
        FileReader reader = new FileReader(fileToSend.getFile());
        entree =  new BufferedReader(reader);

        long timeDebut = new Date().getTime();
        
        // Tant qu'on est pas à la fin du fichier
        while( transfert)
        {
            octectLu= entree.read(ligneLu,octectTraite, size-octectTraite);
            System.out.println("Emission data : "+ligneLu.toString());

            if( octectLu>0  ) // Si le tableau n'est pas vide en envoi les données
            {
                sortie.write(ligneLu);
                sortie.flush();
                octectTraite = octectTraite + octectLu;

            }
            
            if(octectLu == -1){//fin du fichier
                octectTraite = octectTraite + (size-octectTraite);
            }
            // Calcul de la vitesse de transfert
            vitesseTransfert.getVitesse(timeDebut,octectTraite);
            barreDeProgression.setProgressBar(vitesseTransfert);
           
            if(octectTraite == size){
               transfert = false;
           } 
           
       }
       try {
            ClientTCP.sleep(1000);
        } catch (InterruptedException ex) {
            Logger.getLogger(ClientTCP.class.getName()).log(Level.SEVERE, null, ex);
        }        
 }      
    /**
    * Fermer les flux
    */
    private void closeFlux()
    {
        try{

            if( entree!=null )
                entree.close();     
            if( sortie!=null )
                sortie.close();     // Fermeture du flux de sortie
            if( socket!=null)
                socket.close();     // Fermeture du socket
        }catch (java.io.IOException ex){
            Logger.getLogger(ServeurTCP.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
    *  Lance le client TCP pour un transfert de fichier.
    *  Cette methode realise 4 opérations :
    * <ul>
    * <li> Connexion au serveur
    * <li> Ouverture des flux d'entrée et de sortie
    * <li> Envoi des données 
    * <li> Fermeture des flux
    * </ul>
    */
    @Override
    public void run() {
        lancerClient();
    }
}
